#ifndef ERROR_H
#define ERROR_H
#include <stdbool.h>

typedef enum err_level{
	WARNING,
	ERROR,
}err_level_e;


/*
	词法错误码
*/
typedef enum lex_err_code
{
	ID_2_LONG, 		// 标识符过长
	NUM_2_LONG,     // 数字过长
	STR_2_LONG,		// 字符串过长
	COMMENT_NO_END,	// 多行注释没有正常结束
	STR_INCOMPLT,	// 字符串缺少右引号
	CHARA_INCOMPLT, // 字符不完整
	OR_NO_PAIR,		// “||”不完整
	UNRECOGNIZED_TOKEN,	// 无法识别的词法记号
	EMPTY_CHARA,   // 字符常量为空
	UNKNOW_ESCAPE_SEQUENCE, // 未知转义字符
	LEX_ERR_CODE_NUM,
} lex_err_code_e;

/*
	语法错误码
*/
typedef enum syn_err_code
{
	EXPECTED_TYPE,			// 期待类型关键字， data definition has no type
	EXPECTED_ID,              // error: expected identifier
	EXPECTED_LPAREN,
	EXPECTED_RPAREN,
	EXPECTED_LBRACKET,
	EXPECTED_RBRACKET, 
	EXPECTED_LBRACES,
	EXPECTED_RBRACES,
	EXPECTED_COMMA,
	EXPECTED_SEMICOLON, 
	EXPECTED_EQUAL_MARK,
	EXPECTED_COLON,
	EXPECTED_WHILE,
	ARR_SIZE_NEGATIVE_OR_ZERO,  //  error: size of array ‘xx’ is negative
	EXPECTED_LITERAL_OR_EXPR, // 缺少常量或者表达式
	EXPECTED_LITERAL, // 缺少常量
	FORBIDS_NESTED_FUNCTIONS,
	ARR_SIZE_NO_CONSTANT,
	CASE_LABEL_NOT_INT_CONSTANT,
	NEED_STATEMENT,
	IGNORE_TOKEN, 
	STATEMENT_NEVER_BE_EXECUTED, // statement will never be executed
	SYN_ERR_CODE_NUM,  

} syn_err_code_e;



#define LOST  		1
#define NOT_MATCH 	2
#define OTHER       3



/* semantic 语义错误码 */

typedef enum sem_err_code{
    VAR_DECLARED_VOID,					//  error: variable or field ‘xxxxx’ declared void
	VOID_POINTER_NOT_SUPPORTED,
	ARRAY_ELEMENT_TYPE_INVALID,         // 	数组元素类型不支持指针(目前仅支持 int 和 char)
	ARRAY_SIZE_MISSING,                 //   array size missing
	VAR_REDEFINED,                      //  "变量重定义",	
    INT_ARRAY_INITIALIZE_BY_STRING,     // initialize array of ‘int’ from a string literal
	INITIALIZER_STRING_TOO_LONG,   // initializer-string for array of ‘char’ is too long
	EXCESS_ELEMENTS_IN_ARRAY_INIT, //excess elements in array initializer
	ARRAY_INITIALIZE_BY_WRONG_TYPE, //
	CONFLICTING_TYPES, // conflicting types for ‘XXX’; 
	EXTERN_ON_FUNCTION_DEF,     //  'extern' keyword on function definition has no effect 
	FUNCTION_REDEFINED,  
	RETURN_TYPE_IS_VOID_POINTER,    
	IMPLICIT_DECLARATION_OF_FUNCTION, // error: implicit declaration of function ‘foo’ 
	UNDECLARED,   // ‘xxx’ undeclared 
	REDECLARED_AS_DIFFERENT_KIND_SYMBOL, //, ‘xxxx’ redeclared as different kind of symbol
	
	//error:  declaration of ‘x’ with no linkage follows extern declaration
	//error: extern declaration of ‘xxxx’ follows declaration with no linkage
	EXTERN_DECLARATION_AND_NO_LINKAGE_DECLARATION_CONFLICTING, 
	EXPR_NOT_LEFT_VAL,
	TAKE_ADDRESS_OF_ARRAY_OR_POINTER,
	DEREFERENCE_ON_BASE_TYPE,
	OPERANDS_CANNOT_BE_VOID_TYPE,  //  Operands of a binary operator cannot be of type void.
	LVALUE_REQUIRED,               // lvalue required
	ASSIGN_TYPE_NOT_COMPATIBLE,   
	COMPARISON_TYPE_NOT_COMPATIBLE,  
	OPERANDS_TYPE_INVALID, 
	SUBSCRIPTED_VALUE_INVALID,  // 对一个非数组或非指针类型的变量使用​下标运算符 []，
	ARRAY_SUBSCRIPT_IS_NOT_INT,
	CALLED_OBJ_IS_NOT_FUNCTION,  //error: called object ‘a’ is not a function or function pointer
	INCORRECT_TYPE_FOR_FUNCTION_ARGUMENT,    // Incorrect type for function argument
	INVALID_UNARY_OPERATION_ON_FUNCTION,   //Invalid unary operation on a function type.
    HAS_BOTH_EXTERN_AND_INITIALIZER,             //error: ‘a’ has both ‘extern’ and initializer
	INITIALIZE_TYPE_INVALID,
	INITIALIZER_ELEMENT_NOT_CONSTANT,  //error: initializer element is not constant
	INCOMPATIBLE_RETURN_TYPE,  // Incompatible return type​
	EXPR_IS_VOID, // 表达式不能是 void 类型
	DUPLICATE_CASE_VALUE,    //duplicate case value
	MULTIPLE_DEFAULT_LABELS, // multiple default labels in one switch
	BREAK_NOT_WITHIN_LOOP_OR_SWITCH,  //  break statement not within loop or switch
	CONTINUE_NOT_WITHIN_LOOP,   // continue statement not within a loop
	OVERFLOW_IN_CONVERSION_FROM_INT_TO_CHAR, // overflow in conversion from ‘int’ to ‘char’
	SWITCH_QUANTITY_NOT_INT,   //error: switch quantity not an integer
	FUNCTION_NAME_NOT_SUPPORTED, 
	SEM_ERR_CODE_NUM,
}sem_err_code_e;


/* 系统错误码 */
typedef enum system_err_code{
	MEM_ALLOC_FAILED, // 内存分配失败
	POINTER_IS_NULL, // 指针为空
	SYS_ERR_CODE_NUM, 
}system_err_code_e;


void lex_err(lex_err_code_e code, err_level_e lvl);
int show_error_num(void);
void syn_err(syn_err_code_e code,  err_level_e lvl, int cause, const char *name);
void recovery(bool cond, syn_err_code_e code,  err_level_e lvl);
void sem_err(sem_err_code_e code,  err_level_e lvl, const char *name, void *addition);
void system_fatal_err(system_err_code_e code, const char *file_name, int line); 
#define SYSTEM_FATAL_ERR(code)  system_fatal_err(code, __FILE__, __LINE__)


#endif